package com.xhga.transaction.common.annotation;

import com.xhga.transaction.common.annotation.factory.ProxyFactory;
import com.xhga.transaction.common.annotation.factory.XHGARPCProxyFactory;
import com.xhga.transaction.common.util.StringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.support.*;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Map;

import static com.xhga.transaction.common.util.XHGAConfig.USE_PROXY_TYPE;

/**
 * 扫面存在@XHGATransaction注解方法的类,并动态代理加载到spring
 * Created by xhga on 2019/4/23.
 */
@Component
public class XHGAProxyScan implements ApplicationContextAware,InitializingBean {

    private static final Logger logger = LoggerFactory.getLogger(XHGAProxyScan.class);

    @Autowired
    @Qualifier(USE_PROXY_TYPE)
    private ProxyFactory proxyFactory;

    @Override
    public void afterPropertiesSet() throws Exception { }
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        final Map<String, Object> controllerMap = applicationContext.getBeansWithAnnotation(Component.class);
        for (final Object controllerObject : controllerMap.values()) {
            final Class<? extends Object> serviceClass = controllerObject.getClass();

            for (Method method : serviceClass.getDeclaredMethods()) {
                XHGATransaction xhgaTransaction = method.getAnnotation(XHGATransaction.class);
                if (xhgaTransaction != null) {
                    logger.info("XHGA被代理对象:" + serviceClass.getCanonicalName());
                    logger.info("XHGA代理实现:" + proxyFactory);
                    Class<?>[] interfaces = serviceClass.getInterfaces();
                    // 实现接口
                    Class<?> interfaceClass = null;
                    for (Class interfaceV:interfaces) {
                        interfaceClass = interfaceV;
                    }
                    // beanName
                    String beanName = StringUtil.toLowerCaseFirstOne(interfaceClass.getSimpleName());
                    Object bean = applicationContext.getBean(beanName);
                    // 代理对象
                    Object proxyObject = null;
                    try {
                        proxyObject = proxyFactory.getProxy(interfaceClass, bean);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    ConfigurableApplicationContext configurableApplicationContext = (ConfigurableApplicationContext) applicationContext;
                    DefaultListableBeanFactory beanFactory =
                            (DefaultListableBeanFactory) configurableApplicationContext.getBeanFactory();

                    BeanDefinitionBuilder beanDefinitionBuilder =
                            BeanDefinitionBuilder.genericBeanDefinition(proxyObject.getClass());

                    beanDefinitionBuilder.addConstructorArgValue(Proxy.getInvocationHandler(proxyObject));
                    AbstractBeanDefinition beanDefinition = beanDefinitionBuilder.getBeanDefinition();
                    // 设置BeanClass,动态代理类必须设置
                    beanDefinition.setBeanClass(proxyObject.getClass());
                    // 将代理对象注册到spring容器
                    beanFactory.removeBeanDefinition(beanName);
                    beanFactory.registerBeanDefinition(beanName, beanDefinitionBuilder.getRawBeanDefinition());
                    break;
                }
            }
        }
    }

}
